<template>
  <!-- 使用全局注册组件Category -->
  <Category :disabled="!isShowList" />
  <el-card
    v-if="isShowList"
    shadow="hover"
    :body-style="{ padding: '20px' }"
    :style="{ marginTop: '30px' }"
  >
    <template #header>
      <el-button
        type="primary"
        size="default"
        @click="enter"
        :icon="Plus"
        :disabled="!category3Id"
        >添加属性</el-button
      >
    </template>
    <!-- table -->
    <el-table border stripe :data="attrList">
      <el-table-column
        prop="id"
        type="index"
        width="80"
        label="序号"
        align="center"
      />
      <el-table-column
        prop="attrName"
        label="品牌属性"
        width="200"
      ></el-table-column>
      <el-table-column prop="attrValueList" label="品牌属性列表">
        <!-- 使用作用域插槽获取到数据 -->
        <template v-slot="{ row }">
          <el-tag
            v-for="item in row.attrValueList"
            type="success"
            size="default"
            effect="plain"
            :key="item.id"
            >{{ item.valueName }}</el-tag
          >
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" width="240">
        <template v-slot="{ row }">
          <el-button type="warning" :icon="Edit" @click="editAttrValue(row)"
            >修改</el-button
          >
          <el-button type="danger" :icon="Delete" @click="deleteAttr(row)"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>
  </el-card>
  <!-- 添加属性 -->
  <el-card
    v-else
    shadow="hover"
    :body-style="{ padding: '20px' }"
    :style="{ marginTop: '30px' }"
  >
    <template #header>
      <el-form label-width="80px" :inline="true" size="default">
        <el-form-item label="属性名 ">
          <el-input
            placeholder="请输入属性名"
            v-model="newAttrData.attrName"
          ></el-input>
        </el-form-item>
        <el-form-item
          ><el-button
            type="primary"
            @click="addAttrValue"
            :disabled="!newAttrData.attrName"
            >添加属性值</el-button
          ></el-form-item
        >
      </el-form>
    </template>
    <el-table :data="newAttrData.attrValueList">
      <el-table-column label="序号" type="index" width="120" />
      <el-table-column label="属性值名称" prop="valueName">
        <template v-slot="{ row, $index }">
          <el-input
            placeholder="请输入要添加的属性值"
            v-if="row.isEdit"
            v-model="row.valueName"
            size="default"
            ref="iptEle"
            @blur="changeToLook(row, $index)"
            @focus="saveOldValue(row)"
          ></el-input>
          <p v-else @click="changeToEdit(row)">{{ row.valueName }}</p>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="260">
        <template v-slot="{ $index }">
          <el-popconfirm
            title="确认删除该属性值吗?"
            @confirm="deleteAttrValue($index)"
          >
            <template #reference>
              <el-button type="danger" size="default" :icon="Delete"
                >删除</el-button
              >
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <div style="margin-top: 30px">
      <el-button
        type="primary"
        @click="seveOrEditAttr"
        :disabled="
          newAttrData.attrValueList.length <= 0 || !newAttrData.attrName
        "
        >保存</el-button
      >
      <el-button type="info" @click="cancle">取消</el-button>
    </div>
  </el-card>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "Attr",
});
</script>

<script setup lang="ts">
import { Plus, Edit, Delete } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { storeToRefs } from "pinia";
import { nextTick, ref, watch } from "vue";
//引入lodash的深拷贝
import cloneDeep from "lodash/cloneDeep";
//引入api
import {
  requestAttrList,
  requestDeleteAttr,
  requestUpdateOrAddAttr,
} from "@/api/attr";
//引入type
import type {
  attrListType,
  attrListItemType,
  attrValueListType,
} from "@/api/attr";
//引入categroy小仓库
import userAttrStore from "@/stores/attr";
//获取小仓库是咧对象
const attrStore = userAttrStore();
//解构出需要的state
const { category1Id, category2Id, category3Id } = storeToRefs(attrStore);
//存放三级分类的属性列表的响应式数据
const attrList = ref<attrListType>([]);

//封装一个请求attrList函数
const getAttrList = async () => {
  const result = await requestAttrList(
    category1Id.value as number,
    category2Id.value as number,
    category3Id.value as number
  );
  //设置到attrList
  attrList.value = result;
};

//watch监听category3Id的变化
watch(
  category3Id,
  async (newVal) => {
    //问题:当点击其他二级分类或者一级分类的时候,在之前逻辑中把category3Id修改为null 所以watch监听到了 又重新发送请求,这时候会弹出错误. 判断如果为空则直接return 不在执行
    if (!newVal) {
      //把attrList设置为空数组
      attrList.value = [];
      return;
    }
    //当三级分类的发生变化的时候我们需要请求属性列表
    getAttrList();
  },
  //立即监听:当我们跳转到其他组件中在返回会看到之前分类输入框有值 但没有数据展示,所以需要立即监听
  { immediate: true }
);

//定义一个新增品牌属性的一个初始数据,将来新增点击保存的时候,把这个值提交
const newAttrData = ref<attrListItemType>({
  attrName: "",
  categoryId: category3Id.value as number, //固定是category3Id
  categoryLevel: 3, //固定是3
  attrValueList: [],
});

//2.数据保存平台属性页是否展示,可以切换到新增或修改页
const isShowList = ref(true);
//新增品牌属性事件函数
const enter = () => {
  //先切换到新增页
  isShowList.value = false;
  //清空上一次遗留的数据
  newAttrData.value = {
    attrName: "",
    categoryId: category3Id.value as number, //固定是category3Id
    categoryLevel: 3, //固定是3
    attrValueList: [],
  };
};
//退出新增品牌属性事件函数
const cancle = () => {
  //先切换到属性列表页
  isShowList.value = true;
};

//给新增属性 添加属性值的事件函数
const addAttrValue = () => {
  //创建一个属性值的数据
  const newAttrValue = ref({
    //当前新增属性值的内容(目前为空占位,等视图渲染后,在input中数据双向绑定输入)
    valueName: "",
    //当前属性值所在的属性的id(就算是新增,属性没有id,我们也要关联,将来后端添加id的时候,我就有值了)
    attrId: newAttrData.value.id,
    //业务逻辑 编辑模式或者查看模式,增添一个isEdit用来判断是哪个模式 新增属性一定是编辑模式
    isEdit: true,
  });
  //把新增的属性值数据  添加到新属性的  属性值列表的数组中
  newAttrData.value.attrValueList.push(newAttrValue.value);
  //让当前输入框自动获取焦点
  nextTick(() => {
    iptEle.value.focus();
  });
};

//修改某个属性的属性值的事件函数
const editAttrValue = (row: any) => {
  //先切换到新增页
  isShowList.value = false;
  //业务逻辑 编辑模式或者查看模式
  const cloneRow = cloneDeep(row);
  //给每一条数据中都添加一个isEdit值为false
  cloneRow.attrValueList.forEach((item: { isEdit: boolean }) => {
    item.isEdit = false;
  });
  //row是当前这一行请求回来的数据我们需要进行数据回填
  //我们要进行一个深拷贝 不影响原数据
  newAttrData.value = cloneRow;
};

//查看模式切换为编辑模式逻辑
//设置一个同名的ref用来保存ipt
const iptEle = ref();
//从查看模式切换到编辑模式事件函数
const changeToEdit = (row: attrValueListType) => {
  //切换为编辑模式
  row.isEdit = true;
  //让当前输入框自动获取焦点
  nextTick(() => {
    iptEle.value.focus();
  });
};

//定义一个全局变量用来保存旧的值
let oldvalueName = "";
//在input输入框获取焦点的时候拿到旧的值
const saveOldValue = (row: attrValueListType) => {
  //保存旧的值
  oldvalueName = row.valueName;
};

//当ipt失去焦点时候从编辑模式修改为查看模式
const changeToLook = (row: attrValueListType, $index: number) => {
  //切换为查看模式
  row.isEdit = false;
  //判断是否输入为空
  if (!row.valueName.trim()) {
    //如果输入为空且旧值也为空,则证明是新增属性且用户并没有修改或新增,可以直接删除掉
    if (!oldvalueName.trim()) {
      newAttrData.value.attrValueList.splice($index, 1);
    } else {
      //如果有旧值就把旧值还给出去
      row.valueName = oldvalueName;
    }
  }
  //判断输入的内容是否和原来的数据有重复
  //some 数组方法用来返回布尔值 一假即假
  let isRepeat = newAttrData.value.attrValueList.some((item) => {
    //如果自己比自己的话就直接跳过
    if (item === row) {
      return;
    }
    return item.valueName === row.valueName;
  });
  //判断isRepeat
  if (isRepeat) {
    //如果为ture的话则证明有相等的,继续判断是否存在旧值,有旧值的话直接使用旧值
    if (oldvalueName) {
      row.valueName = oldvalueName;
    } else {
      //如果旧值也没有则直接清除
      ElMessage.error("已存在相同属性值");
      newAttrData.value.attrValueList.splice($index, 1);
    }
  }
  //所有逻辑完成后,清空旧值
  oldvalueName = "";
};

//删除某一个attrValue
const deleteAttrValue = ($index: number) => {
  newAttrData.value.attrValueList.splice($index, 1);
};
//点击保存添加或修改请求函数
const seveOrEditAttr = async () => {
  //在发送请求前需要删除数据中我们添加的isEdit
  newAttrData.value.attrValueList.forEach((item) => {
    delete item.isEdit;
  });
  //判断当前的属性值是否为空为空的话就不继续执行保存请求
  if (newAttrData.value.attrValueList.length <= 0) {
    return ElMessage.error("请添加属性值");
  }
  try {
    //发送请求
    await requestUpdateOrAddAttr(newAttrData.value);
    ElMessage.success("保存成功");
    //切换到属性列表页
    isShowList.value = true;
    //重新请求数据
    getAttrList();
  } catch (e) {
    ElMessage.error("保存失败");
  }
};
//删除某条Attr
const deleteAttr = (row: attrListItemType) => {
  ElMessageBox.confirm(`确认删除该条属性?${row.attrName}`, "警告", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
  })
    .then(async () => {
      //发送删除请求
      await requestDeleteAttr(row.id as number);
      ElMessage.success("删除成功");
      //重新获取数据
      getAttrList();
    })
    .catch(() => {});
};
</script>
